
use std::cell::{Ref, RefMut};

#[derive(PartialEq)]
#[derive(Debug)]
pub enum DBError {
    //OpenFailed,
    //CloseFailed,
    //Opened,
    //Closed,
    
    TableExist,
    TableNotExist,

    KeyNotExist,
    KeyExist,

    FsError,
    IoError,
}


pub trait Table{
    fn name(&self) -> &str;

    // if k exist -> return Error KeyExist
    // if k absent -> return length of inserted bytes
    //error -> Err(DBError::X)
    fn insert(&mut self, k: &[u8], v: &[u8]) -> Result<(), DBError>;

    // if k exist -> return removed Value
    // if k absent -> return None
    //error -> Err(DBError::X)
    fn remove(&mut self, k: &[u8]) -> Result<Option<Vec<u8>>, DBError> ;

    //if k exist ->  update it, return Ok(Some(Value))
    //if k absent ->  return Error(KeyNotExist)
    //error -> Err(DBError::X)
    fn update(&mut self, k: &[u8], v: &[u8]) -> Result<Option<Vec<u8>>, DBError>;

    //if k exist ->  replace it, return Ok(Some(Value))
    //if k absent ->  insert it, return Ok(None)
    //error -> Err(DBError::X)
    fn replace(&mut self, k: &[u8], v: &[u8])-> Result<Option<Vec<u8>>, DBError> ;

    // if k exist -> true,
    // if k absent -> false
    fn exist(&self, k: &[u8]) -> bool;

    //if exist ->  return Ok(Some(Value))
    //if absent -> return Ok(None)
    //error -> Err(DBError::X)
    fn get(&self, k: &[u8]) -> Result<Option<&Vec<u8>>, DBError> ;

    //error -> Err(DBError::X)
    fn len(&self) -> usize;
}

pub trait Tables {


    fn create(&mut self, name: &str) -> Result<(), DBError>;
    fn get(&self, name: &str) -> Option<Ref<dyn Table>>;
    fn get_mut(&mut self, name: &str) -> Option<RefMut<dyn Table>>;
    fn drop(&mut self, name: &str) -> Result<(), DBError>;

    fn len(&self) -> usize;
    fn exist(&self, name: &str) -> bool {
        self.get(name).is_some()
    }
}
pub trait DB {
    fn open(&mut self) -> Result<bool, DBError>;
    fn close(&mut self) -> Result<bool, DBError>;
    fn name(&self) -> &str;
    fn tables(&self) -> Ref<dyn Tables> ;
    fn tables_mut(&mut self) -> RefMut<dyn Tables>;
}
